package com.zhiwang.planet.mvvm.viewmodel.main

import android.annotation.SuppressLint
import android.content.Intent
import android.text.TextUtils
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.ObservableBoolean
import androidx.databinding.ObservableField
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStore
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.tencent.bugly.crashreport.CrashReport
import com.uber.autodispose.AutoDispose
import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider
import com.zhiwang.planet.App
import com.zhiwang.planet.BR
import com.zhiwang.planet.R
import com.zhiwang.planet.aop.net.NetWorkRequired
import com.zhiwang.planet.di.ActivityScope
import com.zhiwang.planet.event.*
import com.zhiwang.planet.mvp.v.AuthView
import com.zhiwang.planet.mvvm.model.RestApi
import com.zhiwang.planet.mvvm.model.entity.UserDao
import com.zhiwang.planet.mvvm.model.entity.main.*
import com.zhiwang.planet.mvvm.model.request.DiamondCollectRequest
import com.zhiwang.planet.mvvm.viewmodel.HeaderRecommendItemViewModel
import com.zhiwang.planet.mvvm.viewmodel.RecommendItemViewModel
import com.zhiwang.planet.mvvm.viewmodel.ShareViewModel
import com.zhiwang.planet.ui.MembershipActivity
import com.zhiwang.planet.ui.WebViewActivity
import com.zhiwang.planet.ui.entertain.MiniGameActivity
import com.zhiwang.planet.ui.my.GameCenterActivity
import com.zhiwang.planet.ui.my.MyDetailActivity
import com.zhiwang.planet.ui.my.WithDrawActivity2
import com.zhiwang.planet.ui.my.withdraw.WithDrawRecordFragment
import com.zhiwang.planet.util.*
import com.zhiwang.planet.widget.ShuffleLayout
import io.reactivex.Flowable
import io.reactivex.disposables.Disposable
import io.reactivex.functions.Action
import io.reactivex.functions.Consumer
import me.tatarka.bindingcollectionadapter2.ItemBinding
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.jetbrains.annotations.TestOnly
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.reflect.KClass


class SharedViewModelLazy<VM : ViewModel> constructor(val modelClass: KClass<VM>,
                                                      val viewModelStore: ViewModelStore,
                                                      val factory: ViewModelProvider.Factory) : Lazy<VM> {
    override fun isInitialized(): Boolean {
        return cached == null
    }


    private var cached: VM? = null

    override val value: VM
        get() {
            return cached ?: ViewModelProvider(viewModelStore, factory).get(modelClass.java).also {
                cached = it
            }
        }


}


inline fun <reified VM : ViewModel> sharedViewModels(): Lazy<VM> {

    return SharedViewModelLazy(VM::class, App.instance.viewModelStore, App.instance.viewModelFactory)
}


class MainFactory @Inject constructor(var restApi: RestApi,
                                      var context: AppCompatActivity,
                                      var userDao: UserDao,
                                      var scopeProvider: AndroidLifecycleScopeProvider) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {

        return MainViewModel(restApi, context, userDao, scopeProvider) as T
    }

}

@ActivityScope
class MainViewModel @Inject constructor(var restApi: RestApi,
                                        var context: AppCompatActivity,
                                        var userDao: UserDao,
                                        var scopeProvider: AndroidLifecycleScopeProvider)
    : ViewModel() {
    private var phoneBind: Boolean = false

    val TAG = "MainViewModel"


    init {
        EventBus.getDefault().register(this)
        loopRecGame()
    }

    //用val 修饰似乎更容易链接到xml 布局文件中对应的参数？？？
    val datas = ObservableField<List<Diamond>>(arrayListOf())

    var authView: AuthView? = null

    var smartRefreshLayout: RefreshLayout? = null

    val recommendationData: ObservableField<List<RecommendItemViewModel>> = ObservableField()
    val recommendationItemBinding = ItemBinding.of<RecommendItemViewModel>(BR.recomItemViewModel, R.layout.recommendation_item)

    var disposable: Disposable? = null
    var disposable1: Disposable? = null

    val headerRecommendationItemBinding = ItemBinding.of<HeaderRecommendItemViewModel>(BR.headerRecomItemViewModel, R.layout.header_recommend_item)
    val headerRecommendation: ObservableField<List<HeaderRecommendItemViewModel>> = ObservableField()

    val shareViewModel by sharedViewModels<ShareViewModel>()

    val banners = MutableLiveData<List<Banner>>()

    @NetWorkRequired
    fun start() {
        if (TokenManager.isLoginValid()) {
            disposable = restApi.getIndexData()
                    .androidSchedule()
                    .responseFunc()
                    .`as`(AutoDispose.autoDisposable(scopeProvider))
                    .subscribe({
                        refreshData(it)
                        getIndexActivity()
                    }, {
                        smartRefreshLayout?.finishRefresh()
                        authView?.onError(it)
                    }, {

                    })


//            val subscribe = restApi.getCenterRecommendGames()
//                    .androidSchedule()
//                    .responseFunc()
//                    .subscribe({
//                        scheduleNowIfNoRec(it)
//                    }, {
//
//                    }, {
//
//                    })

        } else {
//            getIndexActivity()
            //使用和登出一样的逻辑
            clear()
            smartRefreshLayout?.finishRefresh()
        }


//        requestRecommendGames()
//        syncLogStatus()
    }

    private fun syncLogStatus() {

//        if (BuildConfig.DEBUG) {
//            TokenManager.clearPhoneLogged()
//            return
//        }

        if (TextUtils.isEmpty(TokenManager.getDeviceId()).not())
            syncLogStatusInternal(TokenManager.getDeviceId())
        else

            AppUtil.getDeviceId {

                syncLogStatusInternal(it)

            }


    }


    private fun syncLogStatusInternal(deviceid: String) {
        restApi.getLoggedStatus(deviceid)
                .arrange(Consumer {

                    if (it == 0)
                        TokenManager.clearPhoneLogged()
                    else TokenManager.setPhoneLogged()

                }, Consumer {

                }, Action {

                })
    }

    private fun scheduleNowIfNoRec(it: List<Game>) {
        centerRecGameList.clear()
        centerRecGameList.addAll(it)
        gameName.set(centerRecGameList[currCenterRecIndex].name)
        gameUrl.set(centerRecGameList[currCenterRecIndex].url)
    }


    var centerRecGameList = arrayListOf<Game>()

    var currCenterRecIndex = -1

    private fun loopRecGame() {

        val subscribe = Flowable.interval(5, TimeUnit.SECONDS)
                .androidSchedule()
                .`as`(AutoDispose.autoDisposable(scopeProvider))
                .subscribe({
                    if (centerRecGameList.isNotEmpty()) {

                        currCenterRecIndex++

                        //此时已经更新了
                        if (currCenterRecIndex < 0 || currCenterRecIndex >= centerRecGameList.size)
                            currCenterRecIndex = 0

                        setRecGame(currCenterRecIndex)

                    }

                }, {
                    currCenterRecIndex = 0
                    it.printStackTrace()
                }, {

                })

    }

    fun setRecGame(index: Int) {
        currCenterRecIndex = index
        gameName.set(centerRecGameList[currCenterRecIndex].name)
        gameUrl.set(centerRecGameList[currCenterRecIndex].url)

    }

    fun myGame() {
        context.quickStartActivity(GameCenterActivity::class.java)
    }

    @SuppressLint("CheckResult")
    private fun requestRecommendGames() {

        restApi.recommendGames()
                .androidSchedule()
                .responseFunc()
                .subscribe({
                    recommendGames.value = it
                }, {

                    authView?.onError(it)
                }, {

                })
    }

    private fun getIndexActivity() {
        restApi.getIndexActivities()
                .androidSchedule()
                .responseFunc()
                .`as`(AutoDispose.autoDisposable(scopeProvider))
                .subscribe({ it ->
                    banners.value = it.headerActivities.map { Banner(it.img!!, it.url!!) }

                    //此时首页数据已经加载完毕，发送一个 显示引导 的事件
                    EventBus.getDefault().post(ShowGuideEvent)
                }, {

                })
    }


    fun onAvatarClick(v: View) {
        if (TokenManager.isLoginValid()) {
            EventBus.getDefault().post(TabChangeEvent(3))
        } else {
            authView?.onAuthExpired()
        }
    }

    private fun refreshData(it: IndexData) {
        userName.set(it.user_info.username)
        incomeForNow.set(it.user_info.gold_z)
        todayIncome.set(it.user_info.revenue)
        smartRefreshLayout?.finishRefresh()
        userDao.addUser(it.user_info)
    }

    var count = 0


    @TestOnly
    private fun mockReward(it: IndexData) {
        count++
    }


    fun onClick() {
        if (TokenManager.isLoginValid())
            return
        else authView?.onAuthExpired()
    }

    fun onGameDiamondClick(v: View) {
        if (TokenManager.isLoginValid()) {
            val recommend = currRecommendGame.get()
            if (recommend != null)
                when (recommend.type) {
                    1 -> {
                        if (TextUtils.isEmpty(recommend.link).not()) {
                            WebViewActivity.load(context, recommend.link!!)
                        }
                    }

                    2 -> {  //原生跳转
                        //此时link 字段是页面 id
                        try {
                            val pageid = recommend.link?.toInt() ?: 0
                            if (pageid in 1..4) {
                                EventBus.getDefault().post(TabChangeEvent(pageid))
                            } else {
                                val intent = Intent()
                                when (pageid) {
                                    //vip页面
                                    5 -> intent.setClass(context, MembershipActivity::class.java)
                                    //提现页面
                                    6 -> intent.setClass(context, WithDrawRecordFragment::class.java)
                                    //我的明细
                                    7 -> intent.setClass(context, MyDetailActivity::class.java)

                                    else -> {
                                        return
                                    }
                                }
                                context.startActivity(intent)
                            }

                        } catch (e: Exception) {
                            CrashReport.postCatchedException(Throwable("页面跳转，link解析错误 ${e.message} -->$recommend", e.cause))
                        }
                    }
                    else -> {
                        if (TextUtils.isEmpty(recommend.link).not()) {
                            WebViewActivity.load(context, recommend.link!!)
                        }
                    }

                }

        } else authView?.onAuthExpired()
    }

    @NetWorkRequired
    fun onDiamondCollect(shuffleLayout: ShuffleLayout, id: String, v: View) {

        if (id.isEmpty()) {
            if (TokenManager.isLoginValid().not()) {
                authView?.onAuthExpired()
            } else if (TextUtils.isEmpty(gameUrl.get()).not()) {
                WebViewActivity.load(context, gameUrl.get()!!)  //跳转游戏
            } else
                start() //获取最新数据
            return
        }
        if (TokenManager.isLoginValid().not()) {
            authView?.onAuthExpired()
            return
        }
        restApi.collectTinyDiamond(DiamondCollectRequest.create(id))
                .androidSchedule()
                .responseFunc()
                .`as`(AutoDispose.autoDisposable(scopeProvider))
                .subscribe({
                    diamond.set(it)
                    shareViewModel.diamondCount.setValue(it)
                    EventBus.getDefault().post(DiamondChangeEvent(it))
                    shuffleLayout.expel(v)
                    if (shuffleLayout.isEmpty())
                        shuffleLayout.setHintWhenEmpty()
                }, {
                    shuffleLayout.expel(v)
                    authView?.onError(it)
                }, {

                })
    }

    fun onDiamondEmpty() = gameName.get()

    fun onRefresh(smartRefresh: RefreshLayout) {
        this.smartRefreshLayout = smartRefresh
        start()
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onLogin(event: LoginEvent) {
        avatarRes.set(0)
        start()
    }

    fun navMiniGame() {
        context.quickStartActivity(MiniGameActivity::class.java)
    }

    fun withdraw() {
        context.quickStartActivity(WithDrawActivity2::class.java)
    }


    fun clear() {
        datas.set(null)
        avatarUrl.set(null)
        avatarRes.set(R.drawable.avatar_not_login)
        currRecommendGame.set(HomeRecommend(null, 2, "0", ""))
        levelRes.set(0)
        userName.set("尚未登录")
        levelVisible.set(false)
        levelName.set("---")
        diamond.set("0.00")
        energy.set("0.00")
        hasNew.set(false)
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onAvatarChange(avatarEvent: AvatarEvent) {
        avatarUrl.set(avatarEvent.url)
    }

    fun doNewerTask() {
        WebViewActivity.load(context, Store.URL_NEWER_TASK)
    }

    fun dispose() {
        disposable?.dispose()
        disposable1?.dispose()
        EventBus.getDefault().unregister(this)
    }

    var name = ObservableField<String>("登录")

    val avatarUrl = ObservableField<String>()

    val avatarRes = ObservableField<Int>(0)

    val userName = ObservableField<String>()

    val incomeForNow = ObservableField<String>()

    val todayIncome = ObservableField<String>()

    val levelName = ObservableField<String>("---")
    val levelRes = ObservableField<Int>(0)

    val diamond = ObservableField<String>("0.00")

    val energy = ObservableField<String>("0.00")

    val hasNew = ObservableBoolean()

    val gameName = ObservableField<String>("")

    val gameUrl = ObservableField<String>("")

    val gameVisisble = ObservableBoolean(false)

    val levelVisible = ObservableBoolean(false)

    val currRecommendGame = ObservableField<HomeRecommend>()

    val recommendGames = MutableLiveData<List<HomeRecommend>>()

    fun video() {
        EventBus.getDefault().post(PlayAdVideoEvent)
    }

    fun navMoney() {
        EventBus.getDefault().post(TabChangeEvent(1))
    }


}